import base64
from PIL import Image
from io import BytesIO
import requests
import tkinter as tk
from tkinter import ttk
from tkinter import messagebox
from docx import Document
from docx.shared import Inches
import os
from colorama import init, Fore, Style

init()  # 初始化 colorama


def setup_tkinter_window():
    """设置Tkinter窗口和滚动条"""
    root = tk.Tk()
    root.title("QR Codes")

    # 获取屏幕尺寸
    screen_width = root.winfo_screenwidth()
    screen_height = root.winfo_screenheight()

    # 设置窗口大小为屏幕大小
    root.geometry(f"{screen_width}x{screen_height}+0+0")

    # 将窗口置于最前
    root.lift()
    root.attributes('-topmost', True)
    root.after_idle(root.attributes, '-topmost', False)

    # 最大化窗口
    root.state('zoomed')

    main_frame, canvas, inner_frame = create_scrollable_frame(root)
    return root, main_frame, canvas, inner_frame


def create_scrollable_frame(root):
    """创建可滚动的框架"""
    main_frame = ttk.Frame(root)
    main_frame.pack(fill=tk.BOTH, expand=True)

    canvas = tk.Canvas(main_frame)
    canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)

    setup_scrollbars(main_frame, canvas)

    inner_frame = ttk.Frame(canvas)
    canvas.create_window((0, 0), window=inner_frame, anchor=tk.NW)

    return main_frame, canvas, inner_frame


def setup_scrollbars(main_frame, canvas):
    """设置滚动条"""
    scrollbar_y = ttk.Scrollbar(main_frame, orient=tk.VERTICAL, command=canvas.yview)
    scrollbar_y.pack(side=tk.RIGHT, fill=tk.Y)

    scrollbar_x = ttk.Scrollbar(main_frame, orient=tk.HORIZONTAL, command=canvas.xview)
    scrollbar_x.pack(side=tk.BOTTOM, fill=tk.X)

    canvas.configure(yscrollcommand=scrollbar_y.set, xscrollcommand=scrollbar_x.set)
    canvas.bind("<Configure>", lambda e: canvas.configure(scrollregion=canvas.bbox("all")))

    # 绑定鼠标滚轮事件
    canvas.bind_all("<MouseWheel>", lambda e: canvas.yview_scroll(int(-1 * (e.delta / 120)), "units"))
    canvas.bind_all("<Shift-MouseWheel>", lambda e: canvas.xview_scroll(int(-1 * (e.delta / 120)), "units"))


def generate_qr_code(content):
    """生成单个二维码"""
    url = 'https://cli.im/Apis/QrCode/saveStatic'
    headers = {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}
    data = {
        "info": content,
        "content": content,
        "level": "H",
        "size": "500",
        "fgcolor": "#000000",
        "bggcolor": "#FFFFFF",
        "transparent": "false",
        "type": "text",
        "codetype": "qr",
        "base64": "",
        "static_create_from": "10003",
        "last_code_info": "{\"last_code_id\":950750839,\"last_code_type\":3,\"last_code_small_type\":\"text\"}",
        "code_small_type": "text",
        "codeimg": "1"
    }

    try:
        response = requests.post(url=url, headers=headers, data=data)
        base64_string = response.json().get('data').get('codeimg_base64')
        base64_image_data = base64_string.split(',')[1]
        return base64.b64decode(base64_image_data)
    except Exception as e:
        print(f"生成二维码 {content} 出现错误: {e}")
        return None


def save_qr_to_word(doc, image_data, index):
    """保存二维码到Word文档"""
    try:
        temp_img_path = f'temp_{index}.png'
        Image.open(BytesIO(image_data)).save(temp_img_path)
        doc.add_paragraph(f'QR Code {index + 1}')
        doc.add_picture(temp_img_path, width=Inches(4.0))
        os.remove(temp_img_path)
    except Exception as e:
        print(f"保存二维码到Word文档时出现错误: {e}")


def display_qr_in_window(inner_frame, image_data, row, col, photo_refs):
    """在窗口中显示二维码，一行显示三个"""
    try:
        photo = tk.PhotoImage(data=image_data)
        photo_refs.append(photo)  # 保持引用

        label = tk.Label(inner_frame, image=photo)
        label.grid(row=row, column=col, padx=10, pady=10)
        label.image = photo

        # 计算下一个位置：如果当前列是2（第三列），则移到下一行的第0列，否则移到下一列
        next_col = 0 if col == 2 else col + 1
        next_row = row + 1 if col == 2 else row

        return next_col, next_row
    except Exception as e:
        print(f"显示二维码时出现错误: {e}")
        return col, row


def process_single_code_mode():
    """处理单个二维码循环模式"""
    while True:
        print("请输入循环次数：")
        print(Fore.GREEN, end='')  # 设置输入文本为绿色
        try:
            loop_num = int(input())
            print(Style.RESET_ALL, end='')  # 重置文本颜色
            break
        except ValueError:
            print(Style.RESET_ALL + "请输入一个整数作为循环次数。")

    while True:
        print("请输入显示选项（1：弹窗显示二维码，2：将生成的二维码保存到Word）：")
        print(Fore.GREEN, end='')  # 设置输入文本为绿色
        display_option = input()
        print(Style.RESET_ALL, end='')  # 重置文本颜色
        if display_option in ['1', '2']:
            break
        print("无效的显示选项，请输入1或2。")

    print("请输入要生成二维码的内容（仅需输入一次）：")
    print(Fore.GREEN, end='')  # 设置输入文本为绿色
    info_content = input()
    print(Style.RESET_ALL, end='')  # 重置文本颜色
    serial_number = int(info_content[-5:])

    return loop_num, display_option, info_content, serial_number


def process_multiple_codes_mode():
    """处理多个二维码模式"""
    while True:
        print("请输入显示选项（1：弹窗显示二维码，2：将生成的二维码保存到Word）：")
        print(Fore.GREEN, end='')  # 设置输入文本为绿色
        display_option = input()
        print(Style.RESET_ALL, end='')  # 重置文本颜色
        if display_option in ['1', '2']:
            break
        print("无效的显示选项，请输入1或2。")

    print("请输入要生成二维码的内容（可输入多个，以逗号或顿号分隔）：")
    print(Fore.GREEN, end='')  # 设置输入文本为绿色
    info_contents = input()
    print(Style.RESET_ALL, end='')  # 重置文本颜色

    # 先替换中文逗号和顿号为英文逗号，然后分割
    info_content_list = [x.strip() for x in info_contents.replace("，", ",").replace("、", ",").split(",") if x.strip()]

    return display_option, info_content_list


def handle_qr_display(display_option, qr_contents):
    """统一处理二维码的显示逻辑"""
    if display_option == '1':
        # 窗口显示模式
        root, _, canvas, inner_frame = setup_tkinter_window()
        photo_refs = []
        current_row = 0
        current_col = 0

        # 添加提示信息
        info_label = tk.Label(inner_frame,
                              text="二维码列表",
                              font=('Arial', 20))
        info_label.grid(row=0, column=0, columnspan=3, pady=10)

        # 从第1行开始显示二维码（第0行是标题）
        current_row = 1

        for content in qr_contents:
            image_data = generate_qr_code(content)
            if image_data:
                current_col, current_row = display_qr_in_window(
                    inner_frame, image_data, current_row, current_col, photo_refs
                )

        # 更新窗口
        root.update_idletasks()
        root.mainloop()
    else:
        # Word文档保存模式
        doc = Document()
        doc.add_heading('QR Code Doc', 0)

        for index, content in enumerate(qr_contents):
            image_data = generate_qr_code(content)
            if image_data:
                save_qr_to_word(doc, image_data, index)

        filename = 'SaveQRcode.docx' if len(qr_contents) == 1 else 'SaveQRcode2.docx'
        doc.save(filename)
        print("所有二维码图片已成功保存到Word文档。")


def generate_serial_qr_contents(info_content, serial_number, loop_num):
    """生成序列化的二维码内容"""
    max_serial_number = 99999
    contents = []

    for i in range(loop_num):
        if serial_number + i > max_serial_number:
            return contents, "已达到生成二维码的上限，后五位流水号最大为99999。"

        new_serial_number_str = str(serial_number + i).zfill(5)
        current_content = f"{info_content[:-5]}{new_serial_number_str}"
        contents.append(current_content)

    return contents, None


def generate_qr_code_according_to_option():
    """优化后的主函数"""
    print("请选择操作模式：\n1. 输入一个二维码信息进行循环保存显示二维码\n2. 手动键入多个二维码信息来显示（不进行循环）")

    print(Fore.GREEN, end='')  # 设置输入文本为绿色
    while True:
        choice = input().strip()
        print(Style.RESET_ALL, end='')  # 重置文本颜色
        if choice in ['1', '2']:
            break
        print("无效的选择，请输入1或2。")
        print(Fore.GREEN, end='')  # 重新设置输入文本为绿色

    if choice == '1':
        loop_num, display_option, info_content, serial_number = process_single_code_mode()
        qr_contents, error_message = generate_serial_qr_contents(info_content, serial_number, loop_num)

        if error_message:
            if display_option == '1':
                messagebox.showinfo("提示", error_message)
            else:
                doc = Document()
                doc.add_heading('QR Code Doc', 0)
                doc.add_paragraph(error_message)
                doc.save('SaveQRcode.docx')
            return

    else:  # choice == '2'
        display_option, qr_contents = process_multiple_codes_mode()

    handle_qr_display(display_option, qr_contents)


if __name__ == "__main__":
    generate_qr_code_according_to_option()
